﻿using System;

namespace NanoMvvm
{
    public class DelegateCommand : CommandBase
    {
        private readonly Action execute;
        private readonly Func<bool> canExecute;

        public DelegateCommand(Action execute)
            : this(execute, null)
        {
        }

        public DelegateCommand(Action execute, Func<bool> canExecute)
        {
            if (execute == null)
            {
                throw new ArgumentNullException("execute");
            }

            this.execute = execute;
            this.canExecute = canExecute;
        }

        protected override void Execute(object parameter)
        {
            execute();
        }

        protected override bool CanExecute(object parameter)
        {
            return canExecute == null || canExecute();
        }

    }

    public sealed class DelegateCommand<T> : CommandBase
    {
        private readonly Action<T> execute;
        private readonly Func<T, bool> canExecute;

        private bool firstRun;

        public DelegateCommand(Action<T> execute)
            : this(execute, null)
        {
        }

        public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
        {
            if (execute == null)
            {
                throw new ArgumentNullException("execute");
            }

            this.execute = execute;
            this.canExecute = canExecute;
            firstRun = true;
        }

        protected override void Execute(object parameter)
        {
            execute((T)parameter);
        }

        protected override bool CanExecute(object parameter)
        {
            if (canExecute != null && parameter == null && typeof(T).IsValueType)
            {
                if (firstRun)
                {
                    firstRun = false;
                    return true;
                }

                return false;
            }

            return canExecute == null || canExecute((T)parameter);
        }
    }

}